package com.uobgroup.ews.uam.web;

import java.io.UnsupportedEncodingException;
import java.security.Principal;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.uobgroup.ews.uam.core.domain.ReferenceType;
import com.uobgroup.ews.uam.core.enums.ScopeType;
import com.uobgroup.ews.uam.core.service.ReferenceService;
import com.uobgroup.ews.uam.core.service.ReferenceTypeService;
import com.uobgroup.ews.uam.web.validation.ReferenceTypeValidator;

@RequestMapping("/referencetypes")
@Controller
public class ReferenceTypeController {

   @Autowired
   ReferenceTypeService referenceTypeService;
   
   @Autowired
   ReferenceService referenceService;
   
   @Autowired
   ReferenceTypeValidator referenceTypeValidator;
   
   @Autowired
   private ReloadableResourceBundleMessageSource messageSource;

   @InitBinder
   protected void InitBinder(WebDataBinder binder){
      binder.setValidator(referenceTypeValidator);
   }

   @RequestMapping(method = RequestMethod.POST, produces = "text/html")
   public String create(@Valid ReferenceType referenceType, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest, Principal principal) {
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, referenceType);
         return "referencetypes/create";
      }
      if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER")) {
         referenceType.setScope(ScopeType.APPLICATION);
      } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER")) {
         referenceType.setScope(ScopeType.SECURITY);
      }
      uiModel.asMap().clear();
      trimProperties(referenceType);
      try {
         referenceType.setLastModificationUserId(principal.getName());
         referenceTypeService.saveReferenceType(referenceType);
      } catch (Exception e) {
         uiModel.addAttribute("messageError", messageSource.getMessage("entity_not_create", new String[] {messageSource.getMessage("menu_item_referencetype_new_label", null, null)}, "", null));
         populateEditForm(uiModel, referenceType);
         return "referencetypes/create";
      }
      return "redirect:/referencetypes/view/" + encodeUrlPathSegment(referenceType.getId().toString(), httpServletRequest);
   }

   @RequestMapping(value = "/create", produces = "text/html")
   public String createForm(Model uiModel) {
      populateEditForm(uiModel, new ReferenceType());
      return "referencetypes/create";
   }

   @RequestMapping(value = "/view/{id}", produces = "text/html")
   public String show(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest, final RedirectAttributes redirectAttrs) {
      ReferenceType referenceType = null; 
      if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER") || httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_CHECKER")) {
         referenceType = referenceTypeService.findReferenceTypeByIdAndApplicationScope(id);
      } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER") || httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_CHECKER")) {
         referenceType = referenceTypeService.findReferenceTypeByIdAndSecurityScope(id);
      }
      if (null == referenceType) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single", new String[] {messageSource.getMessage("menu_item_referencetype_new_label", null, null)}, "", null));
         redirectAttrs.addAttribute("page", "1");
         redirectAttrs.addAttribute("size", "10");
         return "redirect:/referencetypes";
      }
      uiModel.addAttribute("referenceType", referenceType);
      uiModel.addAttribute("itemId", id);
      return "referencetypes/show";
   }

   @RequestMapping(produces = "text/html")
   public String list(@RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, HttpServletRequest httpServletRequest, @ModelAttribute("error") final String error) {
      int sizeNo = size == null ? 10 : size.intValue();
      final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
      float nrOfPages = 0;
      if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER") || httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_CHECKER")) {
         uiModel.addAttribute("referenceTypes", referenceTypeService.findReferenceTypesByApplicationScope(firstResult, sizeNo));
         nrOfPages = (float) referenceTypeService.countReferenceTypesByApplicationScope() / sizeNo;
      } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER") || httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_CHECKER")) {
         uiModel.addAttribute("referenceTypes", referenceTypeService.findReferenceTypesBySecurityScope(firstResult, sizeNo));
         nrOfPages = (float) referenceTypeService.countReferenceTypesBySecurityScope() / sizeNo;
      }
      uiModel.addAttribute("deleteMessageError", error);
      uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
            : nrOfPages));
      return "referencetypes/list";
   }
   
   @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
   public String update(@Valid ReferenceType referenceType, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest, Principal principal, final RedirectAttributes redirectAttrs) {
      ReferenceType rt1 = null;
      long id = referenceType.getId();
      if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER")) {
         rt1 = referenceTypeService.findReferenceTypeByIdAndApplicationScope(id);
      } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER")) {
         rt1 = referenceTypeService.findReferenceTypeByIdAndSecurityScope(id);
      }
      if (null == rt1) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single", new String[] {messageSource.getMessage("menu_item_referencetype_new_label", null, null)}, "", null));
         redirectAttrs.addAttribute("page", "1");
         redirectAttrs.addAttribute("size", "10");
         return "redirect:/references";
      }
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, referenceType);
         return "referencetypes/update";
      }
      uiModel.asMap().clear();
      trimProperties(referenceType);
      try {
         referenceType.setLastModificationUserId(principal.getName());
         referenceTypeService.updateReferenceType(referenceType);
      } catch (Exception e) {
         uiModel.addAttribute("messageError", messageSource.getMessage("entity_not_update", new String[] {messageSource.getMessage("menu_item_referencetype_new_label", null, null)}, null));
         populateEditForm(uiModel, referenceType);
         return "referencetypes/update";
      }
      return "redirect:/referencetypes/view/" + encodeUrlPathSegment(referenceType.getId().toString(), httpServletRequest);
   }

   @RequestMapping(value = "/update/{id}", produces = "text/html")
   public String updateForm(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest, final RedirectAttributes redirectAttrs) {
      
      ReferenceType referenceType = null; 
      if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER")) {
         referenceType = referenceTypeService.findReferenceTypeByIdAndApplicationScope(id);
      } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER")) {
         referenceType = referenceTypeService.findReferenceTypeByIdAndSecurityScope(id);
      }
      if (null == referenceType) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single", new String[] {messageSource.getMessage("menu_item_referencetype_new_label", null, null)}, "", null));
         redirectAttrs.addAttribute("page", "1");
         redirectAttrs.addAttribute("size", "10");
         return "redirect:/references";
      }
      populateEditForm(uiModel, referenceType);
      return "referencetypes/update";
   }

   @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
   public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, HttpServletRequest httpServletRequest, Principal principal, final RedirectAttributes redirectAttrs) {
      ReferenceType referenceType = null;
      Long numOfReference = Long.getLong("0");
      uiModel.asMap().clear();
      
      if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER")) {
         referenceType = referenceTypeService.findReferenceTypeByIdAndApplicationScope(id);
      } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER")) {
         referenceType = referenceTypeService.findReferenceTypeByIdAndSecurityScope(id);
      }
      
      if (null == referenceType) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single", new String[] {messageSource.getMessage("menu_item_referencetype_new_label", null, null)}, "", null));
      } else {
         if (httpServletRequest.isUserInRole("ROLE_APPLICATION_PARAMETER_ADMINISTRATOR_MAKER")) {
            numOfReference = Long.valueOf(referenceService.countReferencesByType(referenceType));
         } else if (httpServletRequest.isUserInRole("ROLE_SECURITY_PARAMETER_ADMINISTRATOR_MAKER")) {
            numOfReference = Long.valueOf(referenceService.countReferencesByType(referenceType));
         }
         
         if (0 == numOfReference.intValue()) {
            try {
               referenceType.setLastModificationUserId(principal.getName());
               referenceTypeService.deleteReferenceType(referenceType);
            } catch (Exception e) {
               redirectAttrs.addFlashAttribute("error", messageSource.getMessage("field_cannot_delete", null, "", null));
            }
         } else if (0 < numOfReference.intValue()) {
            redirectAttrs.addFlashAttribute("error", messageSource.getMessage("field_cannot_delete", null, "", null));
         }
      }
      redirectAttrs.addAttribute("page", (page == null) ? "1" : page.toString());
      redirectAttrs.addAttribute("size", (size == null) ? "10" : size.toString());
      return "redirect:/referencetypes";
   }

   void populateEditForm(Model uiModel, ReferenceType referenceType) {
      uiModel.addAttribute("referenceType", referenceType);
   }

   String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
      String enc = httpServletRequest.getCharacterEncoding();
      if (enc == null) {
         enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
      }
      try {
         pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
      }
      catch (UnsupportedEncodingException uee) {
      }
      return pathSegment;
   }
   
   void trimProperties(ReferenceType referenceType) {
      referenceType.setCode(referenceType.getCode().trim());
      referenceType.setName(referenceType.getName().trim());
   }
}
